<!DOCTYPE html>
<html lang="en-us">
<head><head>
    <meta name="google-site-verification" content="9vIieCe-Qpd78QOmBl63rGtIVbhY6sYyuxX3j8XWBA4" />
    <meta name="baidu-site-verification" content="LRrmH41lz7" />
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="google-site-verification" content="xBT4GhYoi5qRD5tr338pgPM5OWHHIDR6mNg1a3euekI" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    
    <meta name="baidu-site-verification" content="HGLXRsUXC4" />

    
    <meta name="baidu-site-verification" content="code-ANZvlnN0Xr" />

    
    <meta name="description" content="编程 API 方式与Spring 的 ApplicationContextAware 类似。XML的方式依赖于在xml中引入 SOFA 命名空间，利用 Bean 的生命周期管理，进行 Bean 的注入。相比这两种方式，通过 Annotation 方式发布 JVM 服务更加灵活方便，只需要在实现类上加 @SofaService、@SofaRefernce 注解即可进行服务的发布和引用。本文针对 SOFARPC 在注解的支持和使用分原理、源码两部分进行一一介绍。">
    
    <meta name="keyword"  content="liangyuanpeng|LanLiang|OpenYurt|Knative|Pulsar|Prometheus|Halo||边缘计算kubernetes|Docker|CloudNative|Golang|Rust|Istio|微服务">
    <link rel="shortcut icon" href="img/logo.png">


    
    <meta property="og:image" content="https://res.cloudinary.com/lyp/image/upload/v1544363182/hugo/blog.github.io/e64ae3596ed565b8202d395d771665dd.jpg" />
    <meta name="twitter:image" content="https://res.cloudinary.com/lyp/image/upload/v1544363182/hugo/blog.github.io/e64ae3596ed565b8202d395d771665dd.jpg" />


    <title>转|SOFARPC注解支持剖析-liangyuanpeng的博客 | liangyuanpeng&#39;s Blog</title>

    <link rel="canonical" href="/post/sofarpc-annotation/">

    <link rel="stylesheet" href="https://res.cloudinary.com/lyp/raw/upload/v1537369740/hugo/css/iDisqus.min.css"/>

    
    <link rel="stylesheet" href="https://res.cloudinary.com/lyp/raw/upload/v1537369744/hugo/css/bootstrap.min.css">

    
    <link rel="stylesheet" href="https://res.cloudinary.com/lyp/raw/upload/v1537369740/hugo/css/hux-blog.min.css">

    
    <link rel="stylesheet" href="https://res.cloudinary.com/lyp/raw/upload/v1537369740/hugo/css/syntax.css">

    
    <link href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" type="text/css">
    
    
    <script src="https://res.cloudinary.com/lyp/raw/upload/v1537369966/hugo/js/jquery.min.js"></script>

    
    <script src="https://res.cloudinary.com/lyp/raw/upload/v1537369966/hugo/js/bootstrap.min.js"></script>

    
    <script src="https://res.cloudinary.com/lyp/raw/upload/v1537369964/hugo/js/hux-blog.min.js"></script>

    
    <script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "f73bc0092aeb491d89984c0eb5a87ac2"}'></script>
</head>

</head>

<nav class="navbar navbar-default navbar-custom navbar-fixed-top">
    <div class="container-fluid">
        
        <div class="navbar-header page-scroll">
            <button type="button" class="navbar-toggle">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/">Hi,I`m lan</a>
        </div>

        
        
        <div id="huxblog_navbar">
            <div class="navbar-collapse">
                <ul class="nav navbar-nav navbar-right">
                    <li>
                        <a href="/">Home</a>
                    </li>
                    
                    <li>
                        <a href="categories/cloudnative">cloudnative</a>
                    </li>
                    
                    <li>
                        <a href="categories/devops">devops</a>
                    </li>
                    
                    <li>
                        <a href="categories/iot">iot</a>
                    </li>
                    
                    <li>
                        <a href="categories/kubernetes">kubernetes</a>
                    </li>
                    
                    <li>
                        <a href="categories/tech">tech</a>
                    </li>
                    

                    
		            <li>
                        <a href="search">SEARCH <img src="img/search.png" height="15" style="cursor: pointer;"></a>
		            </li>
                    
                </ul>
            </div>
        </div>
        
    </div>
    
</nav>
<script>
    
    
    
    var $body   = document.body;
    var $toggle = document.querySelector('.navbar-toggle');
    var $navbar = document.querySelector('#huxblog_navbar');
    var $collapse = document.querySelector('.navbar-collapse');

    $toggle.addEventListener('click', handleMagic)
    function handleMagic(e){
        if ($navbar.className.indexOf('in') > 0) {
        
            $navbar.className = " ";
            
            setTimeout(function(){
                
                if($navbar.className.indexOf('in') < 0) {
                    $collapse.style.height = "0px"
                }
            },400)
        }else{
        
            $collapse.style.height = "auto"
            $navbar.className += " in";
        }
    }
</script>




<style type="text/css">
    header.intro-header{
        background-image: url('https://res.cloudinary.com/lyp/image/upload/v1544363182/hugo/blog.github.io/e64ae3596ed565b8202d395d771665dd.jpg')
    }
</style>
<header class="intro-header" >
    <div class="container">
        <div class="row">
            <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                <div class="post-heading">
                    <div class="tags">
                       
                       <a class="tag" href="/tags/rpc" title="rpc">
                           rpc
                        </a>
                        
                       <a class="tag" href="/tags/sofa" title="sofa">
                           sofa
                        </a>
                        
                       <a class="tag" href="/tags/sofastack" title="sofastack">
                           sofastack
                        </a>
                        
                       <a class="tag" href="/tags/middleware" title="Middleware">
                           Middleware
                        </a>
                        
                    </div>
                    <h1>转|SOFARPC注解支持剖析</h1>
                    <h2 class="subheading"></h2>
                    <span  class="meta">Posted by 梁远鹏 on 2018-12-11
                        
                        <span id="busuanzi_container_page_pv">|<span id="busuanzi_value_page_pv"></span><span>
                            <span id="/post/sofarpc-annotation/" class="leancloud_visitors meta_data_item" data-flag-title="">
    <span class="post-meta-item-icon">
      <span class="octicon octicon-eye"></span> 
    </span>
    <i class="fa fa-eye"></i>
    <span class="old-visitors-count" style="display: none;"></span>
    <span class="leancloud-visitors-count"></span>
</span>






                            阅读 </span></span>|<span class="post-date">共4405字</span>，阅读约<span class="more-meta"> 9 分钟</span>
                        
                    </span>
                </div>
            </div>
        </div>
    </div>
</header>




<article>
    <div class="container">
        <div class="row">

            
            <div class="
                col-lg-8 col-lg-offset-2
                col-md-10 col-md-offset-1
                post-container">

		
                <header>
                <h2>TOC</h2>
                </header>
                <nav id="TableOfContents">
  <ul>
    <li><a href="#span-data-typecolor-stylecolorrgb38-38-3821注解是什么span"><!-- raw HTML omitted -->2.1、注解是什么<!-- raw HTML omitted --></a></li>
    <li><a href="#span-data-typecolor-stylecolorrgb38-38-3822元注解span"><!-- raw HTML omitted -->2.2、元注解<!-- raw HTML omitted --></a></li>
    <li><a href="#span-data-typecolor-stylecolorrgb38-38-3823注解解析方式span"><!-- raw HTML omitted -->2.3、注解解析方式<!-- raw HTML omitted --></a>
      <ul>
        <li><a href="#231span-data-typecolor-stylecolorrgb38-38-38编译器的扫描span">2.3.1、<!-- raw HTML omitted -->编译器的扫描<!-- raw HTML omitted --></a></li>
        <li><a href="#231span-data-typecolor-stylecolorrgb38-38-38运行期反射span">2.3.1、<!-- raw HTML omitted -->运行期反射<!-- raw HTML omitted --></a></li>
      </ul>
    </li>
  </ul>

  <ul>
    <li><a href="#31span-data-typecolor-stylecolorrgb38-38-38注解说明span">3.1、<!-- raw HTML omitted -->注解说明<!-- raw HTML omitted --></a></li>
    <li><a href="#span-data-typecolor-stylecolorrgb38-38-3832服务发布与引用解析span"><!-- raw HTML omitted -->3.2、服务发布与引用解析<!-- raw HTML omitted --></a>
      <ul>
        <li><a href="#321总体流程">3.2.1、总体流程</a></li>
        <li><a href="#322服务发布">3.2.2、服务发布</a></li>
        <li><a href="#323服务引用">3.2.3、服务引用</a></li>
      </ul>
    </li>
  </ul>
</nav>
		
		<h1 id="1前言">1、前言</h1>
<p>在SOFABoot 环境下，SOFARPC 提供三种方式给开发人员发布和引用 RPC 服务：</p>
<ol>
<li>XML 方式（配置）</li>
<li>Annotation 方式（注解）</li>
<li>编程 API 方式（动态</li>
</ol>
<p><!-- raw HTML omitted -->编程 API 方式与<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->Spring 的 <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->ApplicationContextAware<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --> 类似。<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->XML的方式依赖于在xml中引入 SOFA 命名空间，利用 Bean 的生命周期管理，进行 Bean 的注入。<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->相比这两种方式，通过 Annotation 方式发布 JVM 服务更加灵活方便，只需要在实现类上加 <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->@SofaService<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->、<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->@SofaRefernce<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --> 注解即可进行服务的发布和引用。<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->本文针对 SOFARPC 在注解的支持和使用分原理、源码两部分进行一一介绍。<!-- raw HTML omitted --></p>
<h1 id="span-data-typecolor-stylecolorrgb38-38-382原理介绍span"><!-- raw HTML omitted -->2、原理介绍<!-- raw HTML omitted --></h1>
<h2 id="span-data-typecolor-stylecolorrgb38-38-3821注解是什么span"><!-- raw HTML omitted -->2.1、注解是什么<!-- raw HTML omitted --></h2>
<p><!-- raw HTML omitted -->注解又称为元数据，可以对代码中添加信息，这是一种形式化的方法，可以在稍后的某个时刻非常方便地使用这些数据。这个时刻可能是编译时，也可能是运行时。<!-- raw HTML omitted --></p>
<p><!-- raw HTML omitted -->注解是JDK1.5版本开始引入的一个特性，用于对代码进行说明，可以对包、类、接口、字段、方法参数、局部变量等进行注解。注解的本质就是一个继承了 Annotation 接口的接口。一个注解准确意义上来说，只不过是一种特殊的注释而已，如果没有解析它的代码，它可能连注释都不如。<!-- raw HTML omitted --></p>
<p><!-- raw HTML omitted -->一般常用的注解可以分为三类：<!-- raw HTML omitted --></p>
<ol>
<li><!-- raw HTML omitted -->Java自带的标准注解，包括<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->@Override<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->（标明重写某个方法）、<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->@Deprecated<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->（标明某个类或方法过时）和<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->@SuppressWarnings<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->（标明要忽略的警告）。<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->元注解，元注解是用于定义注解的注解。<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->自定义注解，可以根据自己的需求定义注解。<!-- raw HTML omitted --></li>
</ol>
<h2 id="span-data-typecolor-stylecolorrgb38-38-3822元注解span"><!-- raw HTML omitted -->2.2、元注解<!-- raw HTML omitted --></h2>
<p><!-- raw HTML omitted -->元注解是用于修饰注解的注解，通常用在注解的定义上。JAVA 中有以下几个元注解：<!-- raw HTML omitted --></p>
<ol>
<li><!-- raw HTML omitted -->@Target：注解的作用目标，<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->也就是指明，你的注解到底是用来修饰方法的？修饰类的？还是用来修饰字段属性的，有以下几种类型：<!-- raw HTML omitted --><!-- raw HTML omitted -->
<!-- raw HTML omitted -->ElementType.TYPE：允许被修饰的注解作用在类、接口和枚举上<!-- raw HTML omitted -->
<ul>
<li><!-- raw HTML omitted -->ElementType.FIELD：允许作用在属性字段上<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->ElementType.METHOD：允许作用在方法上<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->ElementType.PARAMETER：允许作用在方法参数上<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->ElementType.CONSTRUCTOR：允许作用在构造器上<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->ElementType.LOCAL_VARIABLE：允许作用在本地局部变量上<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->ElementType.ANNOTATION_TYPE：允许作用在注解上<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->ElementType.PACKAGE：允许作用在包上<!-- raw HTML omitted --></li>
</ul>
</li>
<li><!-- raw HTML omitted -->@Retention：<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->指定了被修饰的注解的生命周期，分以下三种类型：<!-- raw HTML omitted --><!-- raw HTML omitted -->
<ul>
<li><!-- raw HTML omitted -->RetentionPolicy.SOURCE：该注解只保留在一个源文件当中，当编译器将源文件编译成class文件时，它不会将源文件中定义的注解保留在class文件中。<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->RetentionPolicy.CLASS：<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->该注解只保留在一个class文件当中，当加载class文件到内存时，虚拟机会将注解去掉，从而在程序中不能访问。<!-- raw HTML omitted --><!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->RetentionPolicy.RUNTIME：该注解在程序运行期间都会存在内存当中。此时，我们可以通过反射来获得定义在某个类上的所有注解。<!-- raw HTML omitted --></li>
</ul>
</li>
<li><!-- raw HTML omitted -->@Documented：<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->当我们执行 JavaDoc 文档打包时会被保存进 doc 文档，反之将在打包时丢弃。<!-- raw HTML omitted --><!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->@Inherited：<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->解修饰的注解是具有可继承性的，也就说我们的注解修饰了一个类，而该类的子类将自动继承父类的该注解。<!-- raw HTML omitted --><!-- raw HTML omitted --></li>
</ol>
<p><!-- raw HTML omitted -->以 <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->@Override<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --> 为例子：<!-- raw HTML omitted --></p>
<p><img src="https://res.cloudinary.com/lyp/image/upload/v1544534983/hugo/blog.github.io/sofa-rpc/zjzc/1540130591987-c67a035a-7229-4b1d-874b-f5e46e17dded.png" alt="image | left" title=""></p>
<p>当<!-- raw HTML omitted --><!-- raw HTML omitted -->编译器检测到某个方法被修饰了 <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->@Override<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --> 注解，编译器就会检查当前方法的方法签名是否真正重写了父类的某个方法，也就是比较父类中是否具有一个同样的方法签名。<!-- raw HTML omitted --><!-- raw HTML omitted --></p>
<p><!-- raw HTML omitted --><!-- raw HTML omitted -->@Override<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --> <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->仅被编译器可知，编译器在对 java 文件进行编译成字节码的过程中，一旦检测到某个方法上被修饰了该注解，就会去匹对父类中是否具有一个同样方法签名的函数，否则不能通过编译。<!-- raw HTML omitted --><!-- raw HTML omitted --></p>
<h2 id="span-data-typecolor-stylecolorrgb38-38-3823注解解析方式span"><!-- raw HTML omitted -->2.3、注解解析方式<!-- raw HTML omitted --></h2>
<p><!-- raw HTML omitted -->解析一个类或者方法的注解通常有两种形式，一种是编译期直接的扫描，一种是运行期反射。<!-- raw HTML omitted --></p>
<h3 id="231span-data-typecolor-stylecolorrgb38-38-38编译器的扫描span">2.3.1、<!-- raw HTML omitted -->编译器的扫描<!-- raw HTML omitted --></h3>
<p><!-- raw HTML omitted -->指的是编译器在对 java 代码编译字节码的过程中会检测到某个类或者方法被一些注解修饰，这时它就会对于这些注解进行某些处理。典型的就是注解 <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->@Override<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->，一旦编译器检测到某个方法被修饰了 <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->@Override<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --> 注解，编译器就会检查当前方法的方法签名是否真正重写了父类的某个方法，也就是比较父类中是否具有一个同样的方法签名。<!-- raw HTML omitted --></p>
<p><!-- raw HTML omitted --><!-- raw HTML omitted -->这一种情况只适用于那些编译器已经熟知的注解类，比如 JDK 内置的几个注解，而你自定义的注解，编译器是不知道你这个注解的作用的，<!-- raw HTML omitted --><!-- raw HTML omitted --></p>
<h3 id="231span-data-typecolor-stylecolorrgb38-38-38运行期反射span">2.3.1、<!-- raw HTML omitted -->运行期反射<!-- raw HTML omitted --></h3>
<p>首先<!-- raw HTML omitted -->对虚拟机的几个注解相关的属性表进行介绍，先大体了解注解在字节码文件中是如何存储的。虚拟机规范定义了一系列和注解相关的属性表，也就是说，无论是字段、方法或是类本身，如果被注解修饰了，就可以被写进字节码文件。属性表有以下几种：<!-- raw HTML omitted --></p>
<ul>
<li><!-- raw HTML omitted -->RuntimeVisibleAnnotations：运行时可见的注解<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->RuntimeInVisibleAnnotations：运行时不可见的注解<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->RuntimeVisibleParameterAnnotations：运行时可见的方法参数注解<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->RuntimeInVisibleParameterAnnotations：运行时不可见的方法参数注解<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->AnnotationDefault：注解类元素的默认值<!-- raw HTML omitted --></li>
</ul>
<p><!-- raw HTML omitted --><!-- raw HTML omitted -->java.lang.reflect.AnnotatedElement<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --> 接口是所有程序元素（Class、Method和Constructor）的父接口，程序通过反射获取了某个类的 AnnotatedElemen t对象之后，利用 <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->Java 的反射机获取程序代码中的注解，然后根据预先设定的处理规则解析处理相关注解以达到主机本身设定的功能目标。<!-- raw HTML omitted --><!-- raw HTML omitted --></p>
<p>本质上来说，<!-- raw HTML omitted -->反射机制就是注解使用的核心，程序可以调用该对象的以下方法来访问 Annotation信息：<!-- raw HTML omitted --></p>
<ul>
<li><!-- raw HTML omitted -->getAnnotation：返回指定的注解<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->isAnnotationPresent：判定当前元素是否被指定注解修饰<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->getAnnotations：返回所有的注解<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->getDeclaredAnnotation：返回本元素的指定注解<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->getDeclaredAnnotations：返回本元素的所有注解，不包含父类继承而来的<!-- raw HTML omitted --></li>
</ul>
<h1 id="span-data-typecolor-stylecolorrgb38-38-383源码解析span"><!-- raw HTML omitted -->3、源码解析<!-- raw HTML omitted --></h1>
<h2 id="31span-data-typecolor-stylecolorrgb38-38-38注解说明span">3.1、<!-- raw HTML omitted -->注解说明<!-- raw HTML omitted --></h2>
<p><!-- raw HTML omitted -->以 <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->com.alipay.sofa.runtime.api.annotation.SofaReference<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --> 为例子（SofaService 类似），源码如下：<!-- raw HTML omitted --></p>
<p><img src="https://res.cloudinary.com/lyp/image/upload/v1544535004/hugo/blog.github.io/sofa-rpc/zjzc/1540130625068-a828e0fa-d88a-4114-99a1-c897e8c0a066.png" alt="image | left" title=""></p>
<p>基于<!-- raw HTML omitted -->元注解的含义，<!-- raw HTML omitted -->可以了解到：</p>
<ol>
<li><code>@SofaReference</code> 生命周期为 RetentionPolicy.RUNTIME，代表永久保存，可以反射获取；</li>
<li>注解的作用目标 ElementType.FIELD，ElementType.METHOD，说明允许作用在方法和属性字段上；</li>
<li>RPC 的绑定方式有 JVM、BOLT、REST 三种；</li>
<li>默认服务绑定关系为 JVM 方式；</li>
</ol>
<h2 id="span-data-typecolor-stylecolorrgb38-38-3832服务发布与引用解析span"><!-- raw HTML omitted -->3.2、服务发布与引用解析<!-- raw HTML omitted --></h2>
<p>通过 <code>ServiceAnnotationBeanPostProcesso</code> 类中 <code>postProcessAfterInitialization</code>、<code>postProcessBeforeInitialization</code> 方法分别进行服务的发布和引用，其中通过反射对于注解的解析步骤大体相似，主要包含：</p>
<ol>
<li>获取 SofaService.class、SofaReference.class 指定注解</li>
<li>获取的 SOFA 引用的类型，默认为 void</li>
<li>获取的 SOFA 引用的 uniqueId</li>
</ol>
<h3 id="321总体流程">3.2.1、总体流程</h3>
<p>首先看下服务发布和引用<!-- raw HTML omitted --><!-- raw HTML omitted -->整体流程图，主要包含注解解析、组件生成、组件注册几个步骤，后面对每个步骤进行更加详细的解释。<!-- raw HTML omitted --><!-- raw HTML omitted --></p>
<p><img src="https://res.cloudinary.com/lyp/image/upload/v1544535025/hugo/blog.github.io/sofa-rpc/zjzc/1540234052305-10698bc7-79c2-40cb-b47d-61847d1311eb.png" alt="image | left" title=""></p>
<h3 id="322服务发布">3.2.2、服务发布</h3>
<p><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->@SofaService<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --> 的目标是将一个类注册到 SOFA Context 中。<!-- raw HTML omitted --><!-- raw HTML omitted -->发布到 SofaRuntimeContext 的过程其实就是把服务组件对象塞到 <!-- raw HTML omitted -->ConcurrentMap<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->&lt;<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->ComponentName, ComponentInfo<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->&gt; <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->registry<!-- raw HTML omitted --> 对象中，当有其他地方需要查找服务组件的时候，可以通过 registry 进行查找。主要包含以下几个步骤：</p>
<ol>
<li>会遍历 SOFA 绑定关系，通过 handleSofaServiceBinding 方法进行不同类型的 RPC Binding。</li>
<li>生成 ServiceComponent 服务组件对象。</li>
<li><!-- raw HTML omitted --><!-- raw HTML omitted -->调用 <!-- raw HTML omitted --><!-- raw HTML omitted -->ServiceComponent <!-- raw HTML omitted --><!-- raw HTML omitted -->服务组件的 register、resolve、activate方法，逐一调用对应 BindingAdapter 对外暴露服务。<!-- raw HTML omitted --><!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted --><!-- raw HTML omitted -->不同的 BindingAdapter，对应的 outBinding 服务处理策略不一样。对于 JvmBindingAdapter 直接返回空，因为服务不需要暴露给外部，当其他模块调用该服务，直接通过 registry 对象进行查找。其他 RPC BindingAdapter 则将服务信息推送到注册中心 Confreg。<!-- raw HTML omitted --><!-- raw HTML omitted --></li>
<li>将 ServiceComponent 注册到 sofa 的上下文sofaRuntimeContext 中。</li>
</ol>
<h3 id="323服务引用">3.2.3、服务引用</h3>
<p><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->@SofaReference<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --> 的目标则是将 SOFA Context 中的一个服务注册成为 Spring 中的一个bean。<!-- raw HTML omitted --><!-- raw HTML omitted -->基于以上注解解析基础上，<!-- raw HTML omitted --><!-- raw HTML omitted -->主要<!-- raw HTML omitted --><!-- raw HTML omitted -->通过 <code>ReferenceRegisterHelper.registerReference()</code> 方法从SOFA上下文中，拿到服务对应的代理对象。在 <code>registerReference()</code> 方法内部，主要包含以下操作：</p>
<ol>
<li>当注解的 <code>jvmFirst()</code> 为 true 时，会为服务自动再添加一个本地 JVM 的 binding，这样能够做到优先本地调用，避免跨机调用。</li>
<li>生成 ReferenceComponent 服务组件对象。</li>
<li>与 ServiceComponent 处理方式类似<!-- raw HTML omitted --><!-- raw HTML omitted -->，<!-- raw HTML omitted --><!-- raw HTML omitted -->ReferenceComponent 也会<!-- raw HTML omitted --><!-- raw HTML omitted -->添加到 <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->ConcurrentMap<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->&lt;<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->ComponentName, ComponentInfo<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->&gt; <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->registry<!-- raw HTML omitted --> 对象<!-- raw HTML omitted --><!-- raw HTML omitted -->中，分别执行组件的register、resolve、activate 三个方法。其中 register、resolve 方法主要是改变组件的生命周期，<!-- raw HTML omitted --><!-- raw HTML omitted -->代理对象的生成就是在 activate 方法中完成的。</li>
<li>ReferenceComponent 组件通过不同类型的 binding 生成不同类型的代理对象。如果只有一个binding，使用当前 binding 生成代理对象。如果有多个 binding，优先使用 jvm binding 来生成本地调用的代理对象，若本地代理对象不存在，使用远程代理对象。</li>
<li>对于JvmBindingAdapter 的 inBinding 方法，直接借助于动态代理技术进行生成代理对象，对于 RpcBindingAdapter 的 inBinding，在构造的过程存在向注册中心订阅的逻辑。</li>
</ol>
<h1 id="span-data-typecolor-stylecolorrgb38-38-384总结span"><!-- raw HTML omitted -->4、总结<!-- raw HTML omitted --></h1>
<p><!-- raw HTML omitted --><!-- raw HTML omitted -->通过 XML 的方式去配置 SOFA 的 JVM 服务和引用非常简洁，但是多了一定的编码工作量。因此，除了通过 XML 方式发布 JVM 服务和引用之外，SOFA 还提供了 Annotation 的方式来发布和引用 JVM 服务。<!-- raw HTML omitted --><!-- raw HTML omitted --><code>@SofaService</code> 注解省去了 <code>&lt;sofa:service&gt;</code> 声明，但 bean 的定义还是必须要有的。SOFA 实际上是注册了一个BeanPostProcessor 来<!-- raw HTML omitted -->处理 <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->@SofaService<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --> 和 <!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted -->@SofaReference<!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --><!-- raw HTML omitted --> 注解。 <!-- raw HTML omitted --></p>
<p>需要发布引用的对象属于当前 bean 的实例变量，使用 xml 的方式进行服务发布和引用，可以直接通过 Bean 生命周期的 <code>InitializingBean#afterPropertiesSet</code> 方法进行扩展。在工程中注解<!-- raw HTML omitted --><!-- raw HTML omitted -->扫描是一个对所有 bean 的操作，只能通过实现 spring 的 beanpostprocessor 这个接口，另外有些属性可能在发布时需要用到。因此<!-- raw HTML omitted --><!-- raw HTML omitted -->使用注解的方式进行服务发布和引用，分别基于 Bean 生命周期的 <code>BeanPostProcessor#postProcessAfterInitialization</code>、<code>#postProcessBeforeInitialization</code>方法进行扩展。</p>
<p>对比服务的发布和引用的两种常用方式，<!-- raw HTML omitted -->XML 是一种集中式的元数据，与源代码无绑定，注解是一种分散式的元数据，与源代码紧绑定。SOFARPC 初始的版本<!-- raw HTML omitted -->，并不支持通过注解进行 RPC 服务的发布和引用，需要使用 XML 的方式进行配置。后来在开源 SOFARPC 版本中增加这个功能的注解支持，对服务发布和引用做了一个使用方式的补充，而<!-- raw HTML omitted -->对于 XML 与注解的优劣取舍，大家可以团队的规范和个人的评估进行相应的使用。<!-- raw HTML omitted --></p>
<h1 id="5参考文档">5、参考文档</h1>
<ol>
<li><a href="https://en.wikipedia.org/wiki/Java_annotation">Java annotation</a></li>
<li><a href="http://www.sofastack.tech/sofa-rpc/docs/Publish-And-Reference">SOFASTACK 服务发布/服务引用</a></li>
</ol>
<hr>
<p>文章转自<a href="http://www.sofastack.tech/post/xcon7k">剖析 | SOFARPC 框架】之SOFARPC 注解支持剖析</a></p>


        <h2>微信公众号</h2>
<p>扫描下面的二维码关注我们的微信公众号,第一时间查看最新内容。同时也可以关注我的Github，看看我都在了解什么技术，在页面底部可以找到我的Github。</p>
<img src="https://res.cloudinary.com/lyp/image/upload/v1581729955/hugo/blog.github.io/qrcode_for_sikekafeidou.jpg" alt="wechat-account-qrcode">


                <hr>

                <ul class="pager">
                    
                    <li class="previous">
                        <a href="/post/sofarpc-mult-language/" data-toggle="tooltip" data-placement="top" title="转|SOFARPC跨语言支持剖析">&larr; 转|SOFARPC跨语言支持剖析</a>
                    </li>
                    
                    
                    <li class="next">
                        <a href="/post/sofarpc-serializer/" data-toggle="tooltip" data-placement="top" title="转|SOFARPC序列化比较">转|SOFARPC序列化比较 &rarr;</a>
                    </li>
                    
                </ul>

            
<script src="https://utteranc.es/client.js"
repo="liangyuanpeng/liangyuanpeng.github.io"
issue-term="title"
theme="github-light"
crossorigin="anonymous"
async>
</script>



            </div>

            


            
            <div class="
                col-lg-8 col-lg-offset-2
                col-md-10 col-md-offset-1
                sidebar-container">

                
                <section>
                    <hr class="hidden-sm hidden-xs">
                    <h5><a href="/tags/">FEATURED TAGS</a></h5>
                    <div class="tags">
                     
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                            <a href="/tags/blog" title="blog">
                                blog
                            </a>
                        
                    
                        
                    
                        
                            <a href="/tags/chirpstack" title="chirpstack">
                                chirpstack
                            </a>
                        
                    
                        
                    
                        
                            <a href="/tags/ci/cd" title="ci/cd">
                                ci/cd
                            </a>
                        
                    
                        
                    
                        
                            <a href="/tags/cloudnative" title="cloudnative">
                                cloudnative
                            </a>
                        
                    
                        
                            <a href="/tags/cncf" title="cncf">
                                cncf
                            </a>
                        
                    
                        
                    
                        
                            <a href="/tags/docker" title="docker">
                                docker
                            </a>
                        
                    
                        
                            <a href="/tags/docker-compose" title="docker-compose">
                                docker-compose
                            </a>
                        
                    
                        
                    
                        
                    
                        
                    
                        
                            <a href="/tags/fluentd" title="fluentd">
                                fluentd
                            </a>
                        
                    
                        
                    
                        
                    
                        
                            <a href="/tags/halo" title="halo">
                                halo
                            </a>
                        
                    
                        
                            <a href="/tags/hugo" title="hugo">
                                hugo
                            </a>
                        
                    
                        
                            <a href="/tags/image" title="image">
                                image
                            </a>
                        
                    
                        
                    
                        
                            <a href="/tags/iot" title="iot">
                                iot
                            </a>
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                            <a href="/tags/kubernetes" title="kubernetes">
                                kubernetes
                            </a>
                        
                    
                        
                    
                        
                    
                        
                    
                        
                            <a href="/tags/lorawan" title="lorawan">
                                lorawan
                            </a>
                        
                    
                        
                    
                        
                    
                        
                    
                        
                            <a href="/tags/middleware" title="middleware">
                                middleware
                            </a>
                        
                    
                        
                    
                        
                            <a href="/tags/mq" title="mq">
                                mq
                            </a>
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                            <a href="/tags/ops" title="ops">
                                ops
                            </a>
                        
                    
                        
                    
                        
                            <a href="/tags/prometheus" title="prometheus">
                                prometheus
                            </a>
                        
                    
                        
                    
                        
                    
                        
                            <a href="/tags/rpc" title="rpc">
                                rpc
                            </a>
                        
                    
                        
                    
                        
                            <a href="/tags/sofa" title="sofa">
                                sofa
                            </a>
                        
                    
                        
                            <a href="/tags/sofastack" title="sofastack">
                                sofastack
                            </a>
                        
                    
                        
                            <a href="/tags/springboot" title="springboot">
                                springboot
                            </a>
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                    </div>
                </section>



               

                
                
            </div>

            
            
            <div class="
            col-lg- col-lg-offset-2
            col-md-10 col-md-offset-1
            ">
            <section>
                <hr class="hidden-sm hidden-xs">
                

<h2>相关文章</h2>
<ul style="margin-bottom: 25px;">
    
    <li><a href="/post/sofarpc-serializer/">转|SOFARPC序列化比较</a></li>
    
    <li><a href="/post/sofarpc-mult-language/">转|SOFARPC跨语言支持剖析</a></li>
    
    <li><a href="/post/sofarpc-route-impl/">转|SOFARPC路由实现剖析</a></li>
    
    <li><a href="/post/sofarpc-heartbeat-connect/">转|SOFARPC连接管理与心跳剖析</a></li>
    
    <li><a href="/post/sofarpc-sync-async/">转|SOFARPC同步异步实现剖析</a></li>
    
    <li><a href="/post/sofarpc-modle/">转|SOFARPC线程模型剖析</a></li>
    
    <li><a href="/post/sofarpc-trace/">转|SOFARPC链路追踪剖析</a></li>
    
    <li><a href="/post/sofarpc-design/">转|SOFARPC框架之总体设计与扩展机制</a></li>
    
    <li><a href="/post/%E5%8E%BB%E5%93%AA%E5%84%BF%E7%BD%91%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%AE%9E%E7%8E%B0/">去哪儿网消息队列设计与实现</a></li>
    
    <li><a href="/post/awesome-messagequeue/">AWESOME消息队列</a></li>
    
</ul>

            </section>
            </div>
            


        </div>
    </div>
</article>






<footer>
    <div class="container">
        <div class="row">
            <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                <ul class="list-inline text-center">
                   
                    
                    <li>
                        <a target="_blank" href="https://github.com/liangyuanpeng">
                            <span class="fa-stack fa-lg">
                                <i class="fa fa-circle fa-stack-2x"></i>
                                <i class="fa fa-github fa-stack-1x fa-inverse"></i>
                            </span>
                        </a>
                    </li>
                   
                    
                    <li>
                        <a href="mailto:liangyuanpengem@163.com">
                            <span class="fa-stack fa-lg">
                                <i class="fa fa-circle fa-stack-2x"></i>
                                <i class="fa fa-envelope fa-stack-1x fa-inverse"></i>
                            </span>
                        </a>
                    </li>
		    

                    
                    <li>
                        <a href="https://twitter.com/lan31793328">
                            <span class="fa-stack fa-lg">
                                <i class="fa fa-circle fa-stack-2x"></i>
                                <i class="fa fa-twitter fa-stack-1x fa-inverse"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li>
                        <a target="_blank" href="https://www.zhihu.com/people/liangyuanpeng">
                            <span class="fa-stack fa-lg">
                                <i class="fa fa-circle fa-stack-2x"></i>
                                <i class="fa  fa-stack-1x fa-inverse">知</i>
                            </span>
                        </a>
                    </li>
		    
                    
                    <li>
                        <a target="_blank" href="https://weibo.com/u/1908782280">
                            <span class="fa-stack fa-lg">
                                <i class="fa fa-circle fa-stack-2x"></i>
                                <i class="fa fa-weibo fa-stack-1x fa-inverse"></i>
                            </span>
                        </a>
                    </li>
		    

                    

		    
                    
                    
                </ul>
		<p class="copyright text-muted">
                    Copyright &copy; Hi,I`m lan , 2018
                    <br>
                    <a href="https://themes.gohugo.io/hugo-theme-cleanwhite">CleanWhite Hugo Theme</a> by <a href="https://zhaohuabing.com">Huabing</a> |
                    <iframe
                        style="margin-left: 2px; margin-bottom:-5px;"
                        frameborder="0" scrolling="0" width="100px" height="20px"
                        src="https://ghbtns.com/github-btn.html?user=zhaohuabing&repo=hugo-theme-cleanwhite&type=star&count=true" >
                    </iframe>
                </p>
            </div>
        </div>
    </div>
</footer>




<script>
    function async(u, c) {
      var d = document, t = 'script',
          o = d.createElement(t),
          s = d.getElementsByTagName(t)[0];
      o.src = u;
      if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
      s.parentNode.insertBefore(o, s);
    }
</script>






<script>
    
    if($('#tag_cloud').length !== 0){
        async("/js/jquery.tagcloud.js",function(){
            $.fn.tagcloud.defaults = {
                
                color: {start: '#bbbbee', end: '#0085a1'},
            };
            $('#tag_cloud a').tagcloud();
        })
    }
</script>


<script>
    async("https://cdnjs.cloudflare.com/ajax/libs/fastclick/1.0.6/fastclick.js", function(){
        var $nav = document.querySelector("nav");
        if($nav) FastClick.attach($nav);
    })
</script>







<script>
    
    var _baId = 'fad9c137f8ce239f9b323d36c871f8e6';

    
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "//hm.baidu.com/hm.js?" + _baId;
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
</script>







</body>
</html>
